//#include <unistd.h>
#include <stdio.h>
#include <typeinfo>
#include <cassert>
#include <cstring>
#include <map>
#include <vector>
#include <string>

namespace H1
{
    class A
    {
    public:
        A(int m):data_(m){}
        int data_ = 0;
    };

    class B
    {
    public:
        B(double m):data_(m){}
        double data_ = 0.0;
    };
}

class A
{
public:
    A(int m):data_(m){}
    int data_ = 0;
};

class B
{
public:
    B(double m):data_(m){}
    double data_ = 0.0;
};


//key:类型名,value：数据
//然后根据类型名找到对应数据，但转换的时候需要手写


void Test1()
{
    H1::A *a1 = new H1::A(1);
    A *a = new A(2);
     //printf("a1: %s - %s\n", typeid(H1::A).name(), typeid(a1).name());
    assert(strcmp(typeid(*a1).name(), typeid(H1::A).name()) == 0);
    //printf("a: %s- %s\n", typeid(a).name(), typeid(A).name());
    assert(strcmp(typeid(*a).name(), typeid(A).name()) == 0);

    std::map<std::string, void *> t_maps;
    t_maps.insert(std::make_pair(typeid(H1::A).name(), a1));
    t_maps.insert(std::make_pair(typeid(A).name(), a));

    for(auto & item: t_maps)
    {
        if(item.first == typeid(H1::A).name())
        {
            H1::A *tmp = static_cast<H1::A *>(item.second);
            printf("H1::A : %d\n", tmp->data_);
        }
        else
        {
            A *tmp = static_cast<A *>(item.second);
            printf("A : %d\n", tmp->data_);
        }
    }
}

//自定义类型的关联枚举去自己实现转换
struct MyData
{
    enum class TypeEnum
    {
        BType,
        HBType,
    };

    MyData(TypeEnum type, void* d)
    {
        type_ = type;
        data_ = d;
    }

    TypeEnum type_;
    void *data_ = nullptr;
};

void Test2()
{
    H1::B *b1 = new H1::B(2.2);
    B *b = new B(3.3);
    //printf("b1: %s - %s\n", typeid(decltype(b1)).name(), typeid(b1).name());
    //printf("b: %s - %s\n", typeid(*b).name(), typeid(B).name());

    std::vector<MyData> datas;
    MyData d(MyData::TypeEnum::BType, b);
    datas.push_back(d);
    
    MyData d1(MyData::TypeEnum::HBType, b1);
    datas.push_back(d1);

    for(auto& item : datas)
    {
        if(item.type_ == MyData::TypeEnum::BType)
        {
            B *tmp = static_cast<B *>(item.data_);
            printf("B : %f\n", tmp->data_);
        }
        else if(item.type_ == MyData::TypeEnum::HBType)
        {
            H1::B *tmp = static_cast<H1::B *>(item.data_);
            printf("B1 : %f\n", tmp->data_);
        }
    }
}

int main(int argc, char* argv[])
{
    Test1();
    Test2();
    return 0;
}